package huu.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author huu
 * @create 2025-08-27-10:37
 */
public class NettyServer {
    public static void main(String[] args) {
        Map<Channel, List<String>> db = new ConcurrentHashMap<>();
        ServerBootstrap serverBootstrap = new ServerBootstrap()
                //boss group, worker group
                .group(new NioEventLoopGroup(), new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                //一换行符为切割消息
                                .addLast(new LineBasedFrameDecoder(1024))
                                .addLast(new StringDecoder())
                                .addLast(new StringEncoder())
                                //打印接受的消息
                                .addLast(new ReadHandler())
                                .addLast(new dbHandler(db));

                    }
                });
        //ChannelFuture非常重要，是netty异步模型下的核心，
        ChannelFuture bindFuture = serverBootstrap.bind(8080);
        bindFuture.addListener(future -> {
            if (future.isSuccess()) {
                System.out.println(8080 + "绑定成功");
            }
        });
    }

    static class dbHandler extends SimpleChannelInboundHandler<String> {
        private Map<Channel, List<String>> db;

        public dbHandler(Map<Channel, List<String>> db) {
            this.db = db;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
            List<String> list = db.computeIfAbsent(channelHandlerContext.channel(), k -> new ArrayList<>());
            list.add(s);
        }
        @Override
        public void channelInactive(ChannelHandlerContext ctx){
            System.out.println("channel inactive");
            //打印db中内容
            db.get(ctx.channel()).forEach(System.out::println);
            ctx.fireChannelInactive();
        }

    }

    static class ReadHandler extends SimpleChannelInboundHandler<String> {
        //真正读取消息的地方
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
            System.out.println(s);
            String message = s + "huu\n";
            //.channel()调用这个会有走处理器的流程不同，直接调用不会调用后面的处理器
            channelHandlerContext.channel().writeAndFlush(message);
            //为了消息的传递性，下一个处理器也能有这个消息，在netty中事件消息需要手动传播，有方法api,fire...
            channelHandlerContext.fireChannelRead(message);
        }
    }
}
